package com.rongzhe.house.user.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rongzhe.house.common.cache.CommonCacheUtil;
import com.rongzhe.house.common.constants.Constants;
import com.rongzhe.house.common.exception.RongZheBusinessException;
import com.rongzhe.house.common.utils.QiniuFileUploadUtil;
import com.rongzhe.house.common.utils.RandomNumberCode;
import com.rongzhe.house.jms.SmsProcessor;
import com.rongzhe.house.security.AESUtil;
import com.rongzhe.house.security.Base64Util;
import com.rongzhe.house.security.MD5Util;
import com.rongzhe.house.security.RSAUtil;
import com.rongzhe.house.user.dao.UserBaseMapper;
import com.rongzhe.house.user.entity.UserBase;
import com.rongzhe.house.user.entity.UserElement;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.jms.Destination;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by JackWangon[www.aiprogram.top] 2017/7/29.
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserBaseMapper userMapper;

    @Autowired
    private CommonCacheUtil cacheUtil;

    @Autowired
    private SmsProcessor smsProcessor;

    private static final String VERIFYCODE_PREFIX = "verify.code.";
    private static final String SMS_QUEUE = "sms.queue";


    /**
     * @Author JackWang [www.coder520.com]
     * @Date 2017/7/31 23:15
     * @Description 登录业务
     */
    @Override
    @Transactional
    public String login(String data, String key) throws RongZheBusinessException {

        String decryptData = null;
        String token = null;
        try {
            //RSA解密AES的key
            byte[] aesKey = RSAUtil.decryptByPrivateKey(Base64Util.decode(key));
            //AES的key解密AES加密数据
            decryptData = AESUtil.decrypt(data, new String(aesKey, "UTF-8"));
            if (decryptData == null) {
                throw new Exception();
            }
            //拿到提交数据 开始验证逻辑
            JSONObject jsonObject = JSON.parseObject(decryptData);
            String mobile = jsonObject.getString("mobile");//电话
            String code = jsonObject.getString("code");//验证码
            String platform = jsonObject.getString("plantform");//机器类型
            String channelId = jsonObject.getString("channelId");//推送频道编码 单个设备唯一

            if (StringUtils.isBlank(mobile) || StringUtils.isBlank(code) || StringUtils.isBlank(platform) || StringUtils.isBlank(channelId)) {
                throw new Exception();
            }
            //去redis取验证码比较手机号码和验证码是否匹配 若匹配 说明是本人手机
            String verCode = cacheUtil.getCacheValue(VERIFYCODE_PREFIX + mobile);
            System.out.println("缓存验证码:" + verCode);
            System.out.println("输入验证码:" + code);
            UserBase user = null;
            if (code.equals(verCode)) {
                //检查用户是否存在
                user = userMapper.selectByMobile(mobile);
                if (user == null) {
                    //用户不存在 帮用户注册
                    user = new UserBase();
                    user.setMobile(mobile);
                    user.setNickname(mobile);
                    userMapper.insertSelective(user);
                }
            } else {
                throw new RongZheBusinessException("手机号与验证码不匹配");
            }
            //生成token
            try {
                token = this.generateToken(user);
            } catch (Exception e) {
                throw new RongZheBusinessException("fail.to.generate.token");
            }

            UserElement ue = new UserElement();
            ue.setMobile(mobile);
            ue.setUserId(user.getId());
            ue.setToken(token);
            ue.setPlatform(platform);
            ue.setPushChannelId(channelId);
            cacheUtil.putTokenWhenLogin(ue);


        } catch (Exception e) {
            log.error("Fail to decrypt data", e);
            throw new RongZheBusinessException("数据解析错误");
        }

        return token;
    }

    /**
     * @Author JackWang [www.coder520.com]
     * @Date 2017/8/4 11:49
     * @Description 修改用户昵称
     */

    @Transactional
    @Override
    public void modifyNickName(UserBase user) throws RongZheBusinessException {
        userMapper.updateByPrimaryKeySelective(user);
    }

    /**
     * @Author JackWang [www.coder520.com]
     * @Date 2017/8/5 17:22
     * @Description 上传头像
     */
    @Transactional
    @Override
    public String uploadHeadImg(MultipartFile file, Integer userId) throws RongZheBusinessException {

        try {
            //获取user 得到原来的头像地址
            UserBase user = userMapper.selectByPrimaryKey(userId);
            // 调用七牛
            String imgUrlName = QiniuFileUploadUtil.uploadHeadImg(file);
            user.setAvatar(imgUrlName);
            //更新用户头像URL
            userMapper.updateByPrimaryKeySelective(user);
            return Constants.QINIU_HEAD_IMG_BUCKET_URL + "/" + imgUrlName;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RongZheBusinessException("头像上传失败");
        }
    }

    /**
     * @Author JackWang [www.coder520.com]
     * @Date 2017/8/5 17:27
     * @Description 发送验证码
     */
    @Override
    public void sendVercode(String mobile, String ip) throws RongZheBusinessException {
        String verCode = RandomNumberCode.verCode();
        //先存redis  reids缓存检查是否恶意请求 决定是否真的发送验证码
        int result = cacheUtil.cacheForVerificationCode(VERIFYCODE_PREFIX + mobile, verCode, "reg", 60, ip);
        if (result == 1) {
            log.info("当前验证码未过期，请稍后重试");
            throw new RongZheBusinessException("当前验证码未过期，请稍后重试");
        } else if (result == 2) {
            log.info("超过当日验证码次数上线");
            throw new RongZheBusinessException("超过当日验证码次数上限");
        } else if (result == 3) {
            log.info("超过当日验证码次数上限 {}", ip);
            throw new RongZheBusinessException(ip + "超过当日验证码次数上限");
        }
        log.info("Sending verify code {} for phone {}", verCode, mobile);
        //验证码推送到队列
        Destination destination = new ActiveMQQueue(SMS_QUEUE);
        Map<String, String> smsParam = new HashMap<>();
        smsParam.put("mobile", mobile);
        smsParam.put("tplId", Constants.ALSMS_VERCODE_TPLID);
        smsParam.put("vercode", verCode);
        String message = JSON.toJSONString(smsParam);
        smsProcessor.sendSmsToQueue(destination, message);
    }


    private String generateToken(UserBase user)
            throws Exception {
        String source = user.getId() + ":" + user.getMobile() + System.currentTimeMillis();
        return MD5Util.getMD5(source);
    }

    @Override
    public UserBase findById(Integer userId) {
        return userMapper.selectByPrimaryKey(userId);
    }
}
